Let’s learn to make plots in R! While there are some simple plotting functions built into base R (you will often see tutorials that use the plot() command), I encourage you to produce your plots and data visualizations using the ggplot2 package in R. This package takes a little getting used to, but once you understand the syntax you will be making effective graphs and visualizations in no time! Visualizing data is such an important part of the data analysis process: it helps us to better understand the data and its distribution, it allows us to identify and communicate patterns in simple and visually appealing ways, and it enables us to condense a large amount of technical information into a diagram or visual.


#Make sure you download ggplot2 first! Let's load in package and set the working directory.
setwd("/Users/aidenstanton/projects/R")
library(dplyr)
library(tidyr)
library(ggplot2)

#we'll start by loading in some data to play with! We'll use NYC temperature data for this tutorial. 

temps <- read.csv("temps_nyc.csv")

#Take a look at this dataset! It contains mean, min, and max temperatures in NYC for an entire year (2014).
#What if we wanted to plot the temperatures over time? We could plot it using base R like so:

plot(temps$day, temps$actual_mean_temp)


#for all plots, the syntax is usually (x = , y = ) - we'll put time (days) on the horizontal axis, and temperatures on the vertical axis. Putting the time variable on the x-axis is pretty standard. x is for independent variables and y is for dependent variables. 

This plot isn’t bad, but it isn’t very nice looking either. The ggplot2 package gives us so much flexibility to customize our plots - we’ll make a much nicer version of this soon. Before we get to that, we first need to learn a bit about the syntax of ggplot2.

There’s a few important things to point out about the code above. I have put the color = argument in the geom_point layer. This tells R to use the color blue for the points - when we create more complex graphs, being able to customize each geom layer individually becomes really important. Second, the color that I choose comes next in quotation marks. What happens if we leave them out?

blue <- "blue"

#here we've created an object that is assigned the color. 

ggplot(temps, aes(x = day, y = actual_mean_temp)) +
  geom_point(color = blue)

Hopefully that makes sense now! So, the graph of multiple variables looks pretty nice! But, there’s no legend on our graph! How will people know what each color represents? This is a somewhat annoying limitation of ggplot2, and it’s a problem that you’ll come across somewhat frequently.

#Here's the correct plot!
ggplot(temps) +
  geom_point(aes(x = day, y = actual_mean_temp, color = "Mean")) +
  geom_point(aes(x = day, y = actual_min_temp, color = "Min")) +
  geom_point(aes(x = day, y = actual_max_temp, color = "Max")) +
  labs(y = "Temperature", x = "Day", 
       title = "Daily Temperature in New York City, 2014",
       color = "Temperature Values")+
  scale_color_manual(labels = c("Max", "Mean", "Min"), values = c("red", "gray", "blue"))

Why is it so hard to work with this data? This data is in a format called “wide format”, where each category (mean, min, and max) is a different column/variable in the data. Ggplot prefers to work with data in what is called “long format”, where the categories are all neatly gathered in one column. Showing you how to convert from wide to long format is tricky and outside the scope of this tutorial, but I’ll load in a “long format” version of the data to show you the difference.

#load the long data 

long_data <- read.csv("long_temperature.csv")

head(long_data)

Do you see the difference? Now, the category (temp_type, or mean, min, and max) is in one column, while each temperature that corresponds to the temp_type and day is in the temp column. The wide and long data sets are just different ways of storing the same data! Now let’s see how this works in ggplot2.


#Now, instead of three geom layers, we will need to plot the data by three groups: mean, min, and max. Because we are grouping the data in the dataframe by the type of temperature recorded, we need to assign the temp_type column to the group argument. Because each type of temperature will also have a different color, we will assign temp_type to the color argument as well. Let's see what this looks like!

ggplot(long_data, aes(x = Day, y = temp, color = temp_type)) +
  geom_point() +
  labs(y = "Temperature", x = "Day", 
       title = "Daily Temperature in New York City, 2014",
       color = "Temperature (F)")

Do you see why I changed the column names? R uses the categories in the temp_type column to add names to the legend. Keeping the “actual_mean_temp” (and so on) labels would not have been nearly as clear in a legend. In our graphs, we should aim to show complex information in the simplest way possible - having clear legend and axis titles is key to that. Now, in this case, the colors aren’t quite right! Let’s set them manually.

#create the color palette for the data
#Remember, order matters! Based on the order of the legend in the last graph, I will include the color for the max temp, then the mean, then the min. 

colors <- c("red", "gray", "blue")

ggplot(long_data, aes(x = Day, y = temp, color = temp_type)) +
  geom_point() +
  labs(y = "Temperature", x = "Day", 
       title = "Daily Temperature in New York City, 2014",
       color = "Temperature (F)")+
  scale_color_manual(values = colors)

Do you see how much simpler and shorter the ggplot2 code is now? Long format data is easier to work with, but I wanted to show you both data types so that you are prepared for any data format that you might encounter.

If you want to see what other colors are available for creating custom color palettes, check this link: http://www.stat.columbia.edu/~tzheng/files/Rcolor.pdf.

So now you know the basics of graphing with ggplot2! There are just a few more topics to cover that you will find helpful. First, what if I don’t want to use a scatter plot? Ggplot2 comes with a wide range of geom possibilities! It’s so easy to produce different kinds of plots of your data. Let’s make a line plot with the data we already have.


ggplot(long_data, aes(x = Day, y = temp, color = temp_type)) +
  geom_line() +
  labs(y = "Temperature", x = "Day", 
       title = "Daily Temperature in New York City, 2014",
       color = "Temperature (F)")+
  scale_color_manual(values = colors)

The line plot doesn’t look nice and smooth because we’re working with daily data - there are a lot of data points, and the temperatures move around a lot! But as you can see, switching to a line plot was so easy. Next, we can look at a bar plot. Line plots, scatter plots, and bar plots will be the most common plots you’ll use.

#Remember that bar plots don't require x and y variables - we just need one y variable (in this case, temperature) and categories for the x-axis (in this case, temp_type). Let's make a simple bar plot for one day:

day1 <- long_data %>% filter(Day == 1)

ggplot(day1, aes (y =temp, x = temp_type, fill=temp_type)) + 
  geom_bar(stat = "Identity")+
  labs(x = "Temperature Type", y = "Temperature", title = "Temperatures in One Day in NYC") + scale_fill_manual (values = colors)


#Some things to note about this code: because I have included the categories as x-values, I need to include the argument stat = "Identity" in the geom_bar layer. Without going into too much detail, this argument tells R that the height of the columns should be equal to the temp values. Note also that instead of color, we use the fill= argument here - the color argument is for lines and points, while solid polygons need to be assigned colors using the fill argument. As an exercise, try seeing what happens when you use color = instead! When you use fill, the scale_color_manual argument also changes to scale_fill_manual to set the color palette. Finally, R will automatically generate a legend when you assign colors using the group aesthetic - I didn't need a legend in this graph, so I used the theme() argument to set the legend position to "none". This deletes the legend from the plot, and is worth remembering. 

Let’s think about one more way you can customize your plots: adding a visual theme. There are a number of themes you can add to your plot - I like the minimal theme best.


#I prefer the minimal theme that comes loaded with ggplot2 - it makes plots look very sleek 
ggplot(long_data, aes(x = Day, y = temp, group = temp_type, color = temp_type)) +
  geom_line() +
  labs(y = "Temperature", x = "Day", 
       title = "Daily Temperature in New York City, 2014",
       color = "Temperature (F)")+
  scale_color_manual(values = colors) +
  theme_minimal()


library(ggthemes)

Other theme options include theme_dark(), theme_light(), and theme_gray(). If you want additional themes, the ggthemes packages has great options.

And there you have it! You are now a pro at using ggplot2. You should have all the tools you need to make beautiful and effective visualization in R. If you want more information on different types of graphs, or you just want a helpful reference to refer to as you progress through the course, you can find an excellent ggplot2 cheat sheet here: https://www.maths.usyd.edu.au/u/UG/SM/STAT3022/r/current/Misc/data-visualization-2.1.pdf.

Resources

FiveThirtyEight (2014). US. Weather History. [Data Set]. Retrieved from: https://github.com/fivethirtyeight/data/tree/master/us-weather-history.

Prabhakaran, S. (2017). The Complete ggplot2 Tutorial - Part1 | Introduction To ggplot2. Retrieved from: http://r-statistics.co/Complete-Ggplot2-Tutorial-Part1-With-R-Code.html.

LS0tCnRpdGxlOiAiSW50cm8gdG8gZ2dwbG90MiIKb3V0cHV0OiBodG1sX25vdGVib29rCgotLS0KTGV0J3MgbGVhcm4gdG8gbWFrZSBwbG90cyBpbiBSISBXaGlsZSB0aGVyZSBhcmUgc29tZSBzaW1wbGUgcGxvdHRpbmcgZnVuY3Rpb25zIGJ1aWx0IGludG8gYmFzZSBSICh5b3Ugd2lsbCBvZnRlbiBzZWUgdHV0b3JpYWxzIHRoYXQgdXNlIHRoZSBwbG90KCkgY29tbWFuZCksIEkgZW5jb3VyYWdlIHlvdSB0byBwcm9kdWNlIHlvdXIgcGxvdHMgYW5kIGRhdGEgdmlzdWFsaXphdGlvbnMgdXNpbmcgdGhlIGdncGxvdDIgcGFja2FnZSBpbiBSLiBUaGlzIHBhY2thZ2UgdGFrZXMgYSBsaXR0bGUgZ2V0dGluZyB1c2VkIHRvLCBidXQgb25jZSB5b3UgdW5kZXJzdGFuZCB0aGUgc3ludGF4IHlvdSB3aWxsIGJlIG1ha2luZyBlZmZlY3RpdmUgZ3JhcGhzIGFuZCB2aXN1YWxpemF0aW9ucyBpbiBubyB0aW1lISBWaXN1YWxpemluZyBkYXRhIGlzIHN1Y2ggYW4gaW1wb3J0YW50IHBhcnQgb2YgdGhlIGRhdGEgYW5hbHlzaXMgcHJvY2VzczogaXQgaGVscHMgdXMgdG8gYmV0dGVyIHVuZGVyc3RhbmQgdGhlIGRhdGEgYW5kIGl0cyBkaXN0cmlidXRpb24sIGl0IGFsbG93cyB1cyB0byBpZGVudGlmeSBhbmQgY29tbXVuaWNhdGUgcGF0dGVybnMgaW4gc2ltcGxlIGFuZCB2aXN1YWxseSBhcHBlYWxpbmcgd2F5cywgYW5kIGl0IGVuYWJsZXMgdXMgdG8gY29uZGVuc2UgYSBsYXJnZSBhbW91bnQgb2YgdGVjaG5pY2FsIGluZm9ybWF0aW9uIGludG8gYSBkaWFncmFtIG9yIHZpc3VhbC4gCgoKYGBge3J9CgojTWFrZSBzdXJlIHlvdSBkb3dubG9hZCBnZ3Bsb3QyIGZpcnN0ISBMZXQncyBsb2FkIGluIHBhY2thZ2UgYW5kIHNldCB0aGUgd29ya2luZyBkaXJlY3RvcnkuCnNldHdkKCIvVXNlcnMvYWlkZW5zdGFudG9uL3Byb2plY3RzL1IiKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdncGxvdDIpCgojd2UnbGwgc3RhcnQgYnkgbG9hZGluZyBpbiBzb21lIGRhdGEgdG8gcGxheSB3aXRoISBXZSdsbCB1c2UgTllDIHRlbXBlcmF0dXJlIGRhdGEgZm9yIHRoaXMgdHV0b3JpYWwuIAoKdGVtcHMgPC0gcmVhZC5jc3YoInRlbXBzX255Yy5jc3YiKQoKI1Rha2UgYSBsb29rIGF0IHRoaXMgZGF0YXNldCEgSXQgY29udGFpbnMgbWVhbiwgbWluLCBhbmQgbWF4IHRlbXBlcmF0dXJlcyBpbiBOWUMgZm9yIGFuIGVudGlyZSB5ZWFyICgyMDE0KS4KI1doYXQgaWYgd2Ugd2FudGVkIHRvIHBsb3QgdGhlIHRlbXBlcmF0dXJlcyBvdmVyIHRpbWU/IFdlIGNvdWxkIHBsb3QgaXQgdXNpbmcgYmFzZSBSIGxpa2Ugc286CgpwbG90KHRlbXBzJGRheSwgdGVtcHMkYWN0dWFsX21lYW5fdGVtcCkKCiNmb3IgYWxsIHBsb3RzLCB0aGUgc3ludGF4IGlzIHVzdWFsbHkgKHggPSAsIHkgPSApIC0gd2UnbGwgcHV0IHRpbWUgKGRheXMpIG9uIHRoZSBob3Jpem9udGFsIGF4aXMsIGFuZCB0ZW1wZXJhdHVyZXMgb24gdGhlIHZlcnRpY2FsIGF4aXMuIFB1dHRpbmcgdGhlIHRpbWUgdmFyaWFibGUgb24gdGhlIHgtYXhpcyBpcyBwcmV0dHkgc3RhbmRhcmQuIHggaXMgZm9yIGluZGVwZW5kZW50IHZhcmlhYmxlcyBhbmQgeSBpcyBmb3IgZGVwZW5kZW50IHZhcmlhYmxlcy4gCmBgYApUaGlzIHBsb3QgaXNuJ3QgYmFkLCBidXQgaXQgaXNuJ3QgdmVyeSBuaWNlIGxvb2tpbmcgZWl0aGVyLiBUaGUgZ2dwbG90MiBwYWNrYWdlIGdpdmVzIHVzIHNvIG11Y2ggZmxleGliaWxpdHkgdG8gY3VzdG9taXplIG91ciBwbG90cyAtIHdlJ2xsIG1ha2UgYSBtdWNoIG5pY2VyIHZlcnNpb24gb2YgdGhpcyBzb29uLiBCZWZvcmUgd2UgZ2V0IHRvIHRoYXQsIHdlIGZpcnN0IG5lZWQgdG8gbGVhcm4gYSBiaXQgYWJvdXQgdGhlIHN5bnRheCBvZiBnZ3Bsb3QyLiAKCmBgYHtyfQojTGV0J3MgbG9vayBhdCB0aGUgZmlyc3QgbGluZSBvZiBhIGJhc2ljIGdncGxvdCBncmFwaDoKCmdncGxvdCh0ZW1wcywgYWVzKHggPSBkYXksIHkgPSBhY3R1YWxfbWVhbl90ZW1wKSkKCiNXaGVuIHlvdSB1c2UgdGhlIGdncGxvdCgpIGNvbW1hbmQsIHlvdSBuZWVkIHRvIHN1cHBseSBhIGZldyBrZXkgYXJndW1lbnRzLiBUaGUgZmlyc3QgaXMgdGhlIGRhdGFzZXQgLSBpbiB0aGlzIGNhc2UsIHdlIHdpbGwgYmUgdXNpbmcgdGhlIHRlbXBzIGRhdGEgKGFzIHNob3duKS4gVGhlIG5leHQgcGFydCwgY2FsbGVkIHRoZSBhZXN0aGV0aWMgbWFwcGluZyBvciBhZXMgb2YgdGhlIHBsb3QsIHRlbGxzIHVzIHdoYXQgd2Ugd2lsbCBiZSBwbG90dGluZyBmcm9tIHRoZSBkYXRhc2V0LiBMYXRlciwgd2Ugd2lsbCBhbHNvIGluY2x1ZGUgc29tZSBjaGFyYWN0ZXJpc3RpY3Mgb2YgdGhlIHBsb3QgaW4gdGhlIGFlcygpIHNlY3Rpb24uIENhbiB3ZSBwbG90IHRoZSBncmFwaCBub3c/IE5vdCBqdXN0IHlldCEgV2UgbmVlZCB0byBhZGQgYSBnZW9tIGxheWVyIC0gdGhlIGdlb20gbGF5ZXIgdGVsbHMgZ2dwbG90MiB3aGF0IGtpbmQgb2YgdmlzdWFsaXphdGlvbiB0byBwcm9kdWNlIHdpdGggdGhlIGRhdGEuIFdlIHVzZSBhICsgc2lnbiB0byBpbmRpY2F0ZSBhIG5ldyBsYXllciBpbiB0aGUgcGxvdCBsaWtlIHRoaXMgKGhlcmUgSSdtIHVzaW5nIGdlb21fcG9pbnQgdG8gdGVsbCBnZ3Bsb3QyIHRvIGRyYXcgYSBzY2F0dGVyIHBsb3QpOgoKZ2dwbG90KHRlbXBzLCBhZXMoeCA9IGRheSwgeSA9IGFjdHVhbF9tZWFuX3RlbXApKSArCiAgZ2VvbV9wb2ludCgpCgojZ2dwbG90IGZ1bmN0aW9uIChkYXRhIGZyYW1lLCBhZXN0aGV0aWMgbWFwcGluZyAoeCA9IG5hbWUgb2YgaW5kZXBlbmRlbnQgdmFyaWFibGUgaW4gdGhlIGRhdGEgZnJhbWUsIHk9IG5hbWUgb2YgZGVwZW5kZW50IHZhcmlhYmxlIGluIHRoZSBkYXRhIGZyYW1lKSkgKyBnZW9tX3R5cGUgb2YgZ3JhcGgKYGBgCmBgYHtyfQojT25lIG9mIHRoZSBuaWNlIHRoaW5ncyBhYm91dCBnZ3Bsb3QyIGlzIGl0cyBmbGV4aWJpbGl0eS4gV2UgY2FuIGVhc2lseSBjdXN0b21pemUgdGhlIHBsb3QuIE9uY2UgeW91IGdldCB1c2VkIHRvIHRoZSBzeW50YXggb2YgZ2dwbG90MiwgY3VzdG9taXphdGlvbiBpcyB2ZXJ5IHNpbXBsZS4gRm9yIGV4YW1wbGUsIGxldCdzIHN0YXJ0IGJ5IGNoYW5naW5nIHRoZSBjb2xvciBvZiB0aGUgcG9pbnRzOgoKZ2dwbG90KHRlbXBzLCBhZXMoeCA9IGRheSwgeSA9IGFjdHVhbF9tZWFuX3RlbXApKSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICJtZWRpdW1wdXJwbGUiKQoKCiNnZ3Bsb3QgZnVuY3Rpb24gKGRhdGEgZnJhbWUsIGFlc3RoZXRpYyBtYXBwaW5nICh4ID0gbmFtZSBvZiBpbmRlcGVuZGVudCB2YXJpYWJsZSBpbiB0aGUgZGF0YSBmcmFtZSwgeT0gbmFtZSBvZiBkZXBlbmRlbnQgdmFyaWFibGUgaW4gdGhlIGRhdGEgZnJhbWUpKSArIGdlb21fdHlwZSBvZiBncmFwaCArIGdlb21fdHlwZSBvZiBncmFwaCAoY29sb3Igb2YgZGF0YSBwb2ludHMgPSAic2VsZWN0ZWQgY29sb3IiKQpgYGAKVGhlcmUncyBhIGZldyBpbXBvcnRhbnQgdGhpbmdzIHRvIHBvaW50IG91dCBhYm91dCB0aGUgY29kZSBhYm92ZS4gSSBoYXZlIHB1dCB0aGUgY29sb3IgPSBhcmd1bWVudCBpbiB0aGUgZ2VvbV9wb2ludCBsYXllci4gVGhpcyB0ZWxscyBSIHRvIHVzZSB0aGUgY29sb3IgYmx1ZSBmb3IgdGhlIHBvaW50cyAtIHdoZW4gd2UgY3JlYXRlIG1vcmUgY29tcGxleCBncmFwaHMsIGJlaW5nIGFibGUgdG8gY3VzdG9taXplIGVhY2ggZ2VvbSBsYXllciBpbmRpdmlkdWFsbHkgYmVjb21lcyByZWFsbHkgaW1wb3J0YW50LiBTZWNvbmQsIHRoZSBjb2xvciB0aGF0IEkgY2hvb3NlIGNvbWVzIG5leHQgaW4gcXVvdGF0aW9uIG1hcmtzLiBXaGF0IGhhcHBlbnMgaWYgd2UgbGVhdmUgdGhlbSBvdXQ/CgpgYGB7cn0KYmx1ZSA8LSAiYmx1ZSIKCiNoZXJlIHdlJ3ZlIGNyZWF0ZWQgYW4gb2JqZWN0IHRoYXQgaXMgYXNzaWduZWQgdGhlIGNvbG9yLiAKCmdncGxvdCh0ZW1wcywgYWVzKHggPSBkYXksIHkgPSBhY3R1YWxfbWVhbl90ZW1wKSkgKwogIGdlb21fcG9pbnQoY29sb3IgPSBibHVlKQoKYGBgCgoKYGBge3J9CiNXaGF0IGlmIHdlIHdhbnQgdG8gYWRkIGxhYmVscyB0byBvdXIgcGxvdD8gVGhpcyBpcyB2ZXJ5IGVhc3kgdG8gZG8gd2l0aCB0aGUgbGFicyBhcmd1bWVudCwgbGlrZSBzbyAocmVtZW1iZXIgdGhhdCB0aGUgeC1heGlzIGlzIHRoZSBob3Jpem9udGFsIGF4aXMsIHdoaWxlIHRoZSB5LWF4aXMgaXMgdGhlIHZlcnRpY2FsIGF4aXMpOgoKZ2dwbG90KHRlbXBzLCBhZXMoeCA9IGRheSwgeSA9IGFjdHVhbF9tZWFuX3RlbXApKSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICJibHVlIikgKwogIGxhYnMoeSA9ICJNZWFuIFRlbXBlcmF0dXJlIiwgeCA9ICJEYXkiKQoKI2dncGxvdCBmdW5jdGlvbiAoZGF0YSBmcmFtZSwgYWVzdGhldGljIG1hcHBpbmcgKHggPSBuYW1lIG9mIGluZGVwZW5kZW50IHZhcmlhYmxlIGluIHRoZSBkYXRhIGZyYW1lLCB5PSBuYW1lIG9mIGRlcGVuZGVudCB2YXJpYWJsZSBpbiB0aGUgZGF0YSBmcmFtZSkpICsgZ2VvbV90eXBlIG9mIGdyYXBoICsgZ2VvbV90eXBlIG9mIGdyYXBoIChjb2xvciBvZiBkYXRhIHBvaW50cyA9ICJzZWxlY3RlZCBjb2xvciIpICsgbGFiZWwgKHk9IGxhYmVsIG9mIGRlcGVuZGVudCB2YXJpYWJsZSwgeCA9IGxhYmVsIG9mIGluZGVwZW5kZW50IHZhcmlhYmxlKQoKYGBgCmBgYHtyfQojVGhpcyBpcyBzdGFydGluZyB0byBsb29rIHByZXR0eSBuaWNlISBXaGF0IGlmIHdlIHdhbnRlZCB0byBhZGQgYSB0aXRsZSB0b28/CgpnZ3Bsb3QodGVtcHMsIGFlcyh4ID0gZGF5LCB5ID0gYWN0dWFsX21lYW5fdGVtcCkpICsKICBnZW9tX3BvaW50KGNvbG9yID0gImJsdWUiKSArCiAgbGFicyh5ID0gIk1lYW4gVGVtcGVyYXR1cmUiLCB4ID0gIkRheSIsIAogICAgICAgdGl0bGUgPSAiTWVhbiBEYWlseSBUZW1wZXJhdHVyZSBpbiBOZXcgWW9yayBDaXR5LCAyMDE0IikKCiNZb3UnbGwgbm90aWNlIHRoYXQgSSBsaWtlIHRvIHB1dCBlYWNoIG5ldyBhcmd1bWVudCBhZnRlciBhICIrIiBvbiBhIG5ldyBsaW5lIC0geW91IGRvbid0IGhhdmUgdG8gZG8gdGhpcywgYnV0IEkgcHJlZmVyIHRvIGJlY2F1c2UgaXQgbWFrZXMgbXkgY29kZSBtdWNoIGVhc2llciB0byBmb2xsb3cuIEkgYWxzbyBsaWtlIHRvIHB1dCBsb25nZXIgbGFiZWwgbmFtZXMgb24gYSBuZXcgbGluZSAtIGFnYWluLCB0aGlzIHdvbid0IGFmZmVjdCBob3cgdGhlIGNvZGUgcnVucywgaXQganVzdCBtYWtlcyBpdCBtb3JlIHJlYWRhYmxlLiAKCiNnZ3Bsb3QgZnVuY3Rpb24gKGRhdGEgZnJhbWUsIGFlc3RoZXRpYyBtYXBwaW5nICh4ID0gbmFtZSBvZiBpbmRlcGVuZGVudCB2YXJpYWJsZSBpbiB0aGUgZGF0YSBmcmFtZSwgeT0gbmFtZSBvZiBkZXBlbmRlbnQgdmFyaWFibGUgaW4gdGhlIGRhdGEgZnJhbWUpKSArIGdlb21fdHlwZSBvZiBncmFwaCArIGdlb21fdHlwZSBvZiBncmFwaCAoY29sb3Igb2YgZGF0YSBwb2ludHMgPSAic2VsZWN0ZWQgY29sb3IiKSArIGxhYmVsICh5PSBsYWJlbCBvZiBkZXBlbmRlbnQgdmFyaWFibGUsIHggPSBsYWJlbCBvZiBpbmRlcGVuZGVudCB2YXJpYWJsZSkgKyB0aXRsZSA9ICJ0aXRsZSBvZiBncmFwaCIKCmBgYApgYGB7cn0KI0J1dCB3aGF0IGlmIHdlIHdhbnRlZCB0byBhbHNvIGdyYXBoIHRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtIHRlbXBlcmF0dXJlcyBvbiB0aGUgc2FtZSBwbG90PyB0aGlzIGlzIGFsc28gdmVyeSBlYXN5IHRvIGRvISBXZSBqdXN0IG5lZWQgdG8gdXNlIGEgZ2VvbV9wb2ludCBsYXllciBmb3IgZWFjaCB2YXJpYWJsZSB3ZSB3YW50IHRvIHBsb3QuIAoKI2hlcmUgd2Ugc3RhcnQgYnkgdGVsbGluZyBSIHRoYXQgd2Ugd2FudCB0byB1c2UgdGhlIHRlbXBzIGRhdGEgZm9yIG91ciBwbG90CmdncGxvdCh0ZW1wcykgKwogICNmb3IgZWFjaCBuZXcgZ2VvbV9wb2ludCBsYXllciwgSSBuZWVkIHRvIGluY2x1ZGUgYSBuZXcgYWVzdGhldGljIG1hcHBpbmcKICAjdGhpcyB0ZWxscyBSIHdoaWNoIHZhcmlhYmxlIHRvIHVzZSBpbiB0aGUgcGxvdAogIGdlb21fcG9pbnQoYWVzKHggPSBkYXksIHkgPSBhY3R1YWxfbWVhbl90ZW1wKSwgY29sb3IgPSAiZ3JheSIpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gZGF5LCB5ID0gYWN0dWFsX21pbl90ZW1wKSwgY29sb3IgPSAiYmx1ZSIpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gZGF5LCB5ID0gYWN0dWFsX21heF90ZW1wKSwgY29sb3IgPSAicmVkIikgKwogIGxhYnMoeSA9ICJUZW1wZXJhdHVyZSIsIHggPSAiRGF5IiwgCiAgICAgICB0aXRsZSA9ICJEYWlseSBUZW1wZXJhdHVyZSBpbiBOZXcgWW9yayBDaXR5LCAyMDE0IikKCiNOb3RpY2UgaGVyZSB0aGF0IHRoZSBjb2xvciBhcmd1bWVudHMgYXJlIG91dHNpZGUgb2YgdGhlIGFlcygpIGFyZ3VtZW50LiBUaGlzIGlzIGludGVudGlvbmFsIC0gb25seSBhcmd1bWVudHMgdGhhdCBkZXBlbmQgb24gdmFyaWFibGVzIGluIHRoZSBkYXRhc2V0IHNob3VsZCBiZSBpbiB0aGUgYWVzKCkgYXJndW1lbnQuIFdoYXQgZG9lcyB0aGF0IG1lYW4/IEluIHRoaXMgY2FzZSwgdGhlIGNvbG9yICJncmF5IiBkb2Vzbid0IGRlcGVuZCBvbiBhbnl0aGluZyBpbiB0aGUgZGF0YSAtIGZvciBleGFtcGxlLCB0aGUgY29sb3IgZG9lc24ndCBjaGFuZ2UgZm9yIGxvd2VyIG9yIGhpZ2hlciB2YWx1ZXMuIFRoZSBlbnRpcmUgZ2VvbV9wb2ludCBsYXllciBpcyBqdXN0IGdyYXkuIElmIHdlIGhhZCBhIHZhcmlhYmxlIGNhbGxlZCAiY29sb3IiIGluIHRoZSBkYXRhc2V0LCBvciBpZiB3ZSB3YW50ZWQgdGhlIGNvbG9ycyB0byBjaGFuZ2UgYmFzZWQgb24gdGVtcGVyYXR1cmUgdmFsdWVzLCB3ZSBjb3VsZCBwdXQgY29sb3IgaW5zaWRlIHRoZSBhZXMoKS4gCgpgYGAKYGBge3J9CmdncGxvdCh0ZW1wcykgKwogIGdlb21fcG9pbnQoYWVzKHggPSBkYXksIHkgPSBhY3R1YWxfbWVhbl90ZW1wLCBjb2xvciA9IGFjdHVhbF9tZWFuX3RlbXApKSArCiAgbGFicyh5ID0gIk1lYW4gVGVtcGVyYXR1cmUiLCB4ID0gIkRheSIsIAogICAgICAgdGl0bGUgPSAiTWVhbiBEYWlseSBUZW1wZXJhdHVyZSBpbiBOZXcgWW9yayBDaXR5LCAyMDE0IiwKICAgICAgIGNvbG9yID0gIk1lYW4gVGVtcGVyYXR1cmUgKEYpIikKCiN0aGlzIGlzIGNvbG9yIGNoYW5nZSBiYXNlZCBvbiB2YXJpYWJsZSB2YWx1ZXMgbG9va3MgbGlrZQpgYGAKCkhvcGVmdWxseSB0aGF0IG1ha2VzIHNlbnNlIG5vdyEgU28sIHRoZSBncmFwaCBvZiBtdWx0aXBsZSB2YXJpYWJsZXMgbG9va3MgcHJldHR5IG5pY2UhIEJ1dCwgdGhlcmUncyBubyBsZWdlbmQgb24gb3VyIGdyYXBoISBIb3cgd2lsbCBwZW9wbGUga25vdyB3aGF0IGVhY2ggY29sb3IgcmVwcmVzZW50cz8gVGhpcyBpcyBhIHNvbWV3aGF0IGFubm95aW5nIGxpbWl0YXRpb24gb2YgZ2dwbG90MiwgYW5kIGl0J3MgYSBwcm9ibGVtIHRoYXQgeW91J2xsIGNvbWUgYWNyb3NzIHNvbWV3aGF0IGZyZXF1ZW50bHkuIAoKYGBge3J9CgojV2UnbGwgbWFudWFsbHkgc2V0IHRoZSBjb2xvcnMgaW4gdGhlIGxlZ2VuZCB1c2luZyBzY2FsZV9jb2xvcl9tYW51YWwuRm9yIHNvbWUgcmVhc29uLCBpZiB5b3Ugc2V0IHRoZSBjb2xvcnMgYWxsIGF0IG9uY2UsIFIgd2lsbCBnZW5lcmF0ZSBhIGxlZ2VuZDsgaWYgeW91IHNldCBlYWNoIGNvbG9yIGluZGl2aWR1YWxseSBpbiB0aGUgZ2VvbV9wb2ludCBsYXllciwgaXQgd29uJ3QuIEkgZG9uJ3QgbWFrZSB0aGUgcnVsZXMsIEkganVzdCBmb2xsb3cgdGhlbSEgV2hlbiB5b3Ugc2V0IHRoZSBjb2xvcnMgbWFudWFsbHksIHlvdSBoYXZlIHRvIHRlbGwgUiB3aGF0IGxhYmVsIHlvdSdkIGxpa2UgdG8gdXNlIGZvciBlYWNoIGdlb20gbGF5ZXIuIEhlcmUsIEkndmUgc2V0IHRoZSBsYWJlbCBuYW1lcyB1c2luZyBjb2xvciA9ICIiIGluc2lkZSB0aGUgYWVzdGhldGljIG1hcHBpbmcgaW4gdGhlIGdlb20gbGF5ZXIuIAoKZ2dwbG90KHRlbXBzKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRheSwgeSA9IGFjdHVhbF9tZWFuX3RlbXAsIGNvbG9yID0gIk1lYW4iKSkgKwogIGdlb21fcG9pbnQoYWVzKHggPSBkYXksIHkgPSBhY3R1YWxfbWluX3RlbXAsIGNvbG9yID0gIk1pbiIpKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRheSwgeSA9IGFjdHVhbF9tYXhfdGVtcCwgY29sb3IgPSAiTWF4IikpICsKICBsYWJzKHkgPSAiVGVtcGVyYXR1cmUiLCB4ID0gIkRheSIsIAogICAgICAgdGl0bGUgPSAiRGFpbHkgVGVtcGVyYXR1cmUgaW4gTmV3IFlvcmsgQ2l0eSwgMjAxNCIsCiAgICAgICAjc2luY2UgdGhlIGxlZ2VuZCBpcyBiYXNlZCBvbiB0aGUgY29sb3IgbWFwcGluZywgdXNlIGNvbG9yID0gdG8gc2V0IHRoZSBsZWdlbmQgdGl0bGUKICAgICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIFZhbHVlcyIpKwogIHNjYWxlX2NvbG9yX21hbnVhbChsYWJlbHMgPSBjKCJNYXgiLCAiTWVhbiIsICJNaW4iKSwgdmFsdWVzID0gYygicmVkIiwgImdyYXkiLCAiYmx1ZSIpKQoKI0luIHNjYWxlX2NvbG9yX21hbnVhbCwgd2Ugc3RhcnQgYnkgdGVsbGluZyBSIHdoaWNoIGxhYmVscyB0byB1c2UgdG8gZ2VuZXJhdGUgdGhlIGNvbG9yIHNjaGVtZTsgaW4gdGhpcyBjYXNlLCBpdCdzIHRoZSBzYW1lIGxhYmVscyB3ZSBqdXN0IHNldCBhYm92ZS4gVGhlbiwgd2UgaGF2ZSB0byB0ZWxsIFIgd2hpY2ggY29sb3JzIHRvIHVzZSBmb3IgZWFjaCBsYWJlbC4gQmVjYXVzZSB0aGVyZSBhcmUgdGhyZWUgY29sb3IgdmFsdWVzIHRvIHNldCwgbm90ZSB0aGF0IHdlIGhhdmUgdG8gdXNlIGMoKSBhcm91bmQgdGhlIGxpc3Qgb2YgdmFyaWFibGUgbmFtZXMgYW5kIGNvbG9ycy4gCgojU2NhbGVfY29sb3JfbWFudWFsIG9mdGVuIGludm9sdmVzIHNvbWUgZ3Vlc3NpbmcgYW5kIGNoZWNraW5nIHdpdGggdGhlIG9yZGVyIG9mIHRoZSBjb2xvcnMgLSBmb3Igc29tZSByZWFzb24sIFIgd2FudGVkIHRvIHVzZSB0aGUgZmlyc3QgY29sb3IgZm9yIHRoZSBtYXggdGVtcGVyYXR1cmUsIHRoZSBzZWNvbmQgZm9yIHRoZSBtZWFuLCBhbmQgdGhlIHRoaXJkIGZvciB0aGUgbWluLiBUaGlzIG9yZGVyIG1ha2VzIG5vIHNlbnNlLCBidXQgaXQgaXMgYWxzbyBub3QgZWFzeSB0byBjaGFuZ2UuIEdlbmVyYWxseSBSIGRlZmF1bHRzIHRvIGFscGhhYmV0aWNhbCBvcmRlciwgcmVnYXJkbGVzcyBvZiB0aGUgb3JkZXIgeW91IHNwZWNpZnkgZWFjaCBsYXllciBpbiBhIHBsb3QuIElmIHlvdSBub3RpY2UgdGhhdCB0aGUgY29sb3JzIGluIHlvdXIgZ3JhcGggZG9uJ3QgbWF0Y2ggdXAsIHRoZSBlYXNpZXN0IGZpeCBpcyB0byBqdXN0IGNoYW5nZSB0aGUgb3JkZXIgdGhhdCB5b3UgbGlzdGVkIHRoZSBjb2xvcnMgYW5kIHZhcmlhYmxlIG5hbWVzIHNvIHRoYXQgaXQgbWF0Y2hlcyBSJ3MgZGVmYXVsdCBvcmRlcmluZy4gVGhhdCdzIHdoYXQgSSBkaWQgYmVsb3cuIApgYGAKYGBge3J9CiNIZXJlJ3MgdGhlIGNvcnJlY3QgcGxvdCEKZ2dwbG90KHRlbXBzKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRheSwgeSA9IGFjdHVhbF9tZWFuX3RlbXAsIGNvbG9yID0gIk1lYW4iKSkgKwogIGdlb21fcG9pbnQoYWVzKHggPSBkYXksIHkgPSBhY3R1YWxfbWluX3RlbXAsIGNvbG9yID0gIk1pbiIpKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRheSwgeSA9IGFjdHVhbF9tYXhfdGVtcCwgY29sb3IgPSAiTWF4IikpICsKICBsYWJzKHkgPSAiVGVtcGVyYXR1cmUiLCB4ID0gIkRheSIsIAogICAgICAgdGl0bGUgPSAiRGFpbHkgVGVtcGVyYXR1cmUgaW4gTmV3IFlvcmsgQ2l0eSwgMjAxNCIsCiAgICAgICBjb2xvciA9ICJUZW1wZXJhdHVyZSBWYWx1ZXMiKSsKICBzY2FsZV9jb2xvcl9tYW51YWwobGFiZWxzID0gYygiTWF4IiwgIk1lYW4iLCAiTWluIiksIHZhbHVlcyA9IGMoInJlZCIsICJncmF5IiwgImJsdWUiKSkKYGBgCgpXaHkgaXMgaXQgc28gaGFyZCB0byB3b3JrIHdpdGggdGhpcyBkYXRhPyBUaGlzIGRhdGEgaXMgaW4gYSBmb3JtYXQgY2FsbGVkICJ3aWRlIGZvcm1hdCIsIHdoZXJlIGVhY2ggY2F0ZWdvcnkgKG1lYW4sIG1pbiwgYW5kIG1heCkgaXMgYSBkaWZmZXJlbnQgY29sdW1uL3ZhcmlhYmxlIGluIHRoZSBkYXRhLiBHZ3Bsb3QgcHJlZmVycyB0byB3b3JrIHdpdGggZGF0YSBpbiB3aGF0IGlzIGNhbGxlZCAibG9uZyBmb3JtYXQiLCB3aGVyZSB0aGUgY2F0ZWdvcmllcyBhcmUgYWxsIG5lYXRseSBnYXRoZXJlZCBpbiBvbmUgY29sdW1uLiBTaG93aW5nIHlvdSBob3cgdG8gY29udmVydCBmcm9tIHdpZGUgdG8gbG9uZyBmb3JtYXQgaXMgdHJpY2t5IGFuZCBvdXRzaWRlIHRoZSBzY29wZSBvZiB0aGlzIHR1dG9yaWFsLCBidXQgSSdsbCBsb2FkIGluIGEgImxvbmcgZm9ybWF0IiB2ZXJzaW9uIG9mIHRoZSBkYXRhIHRvIHNob3cgeW91IHRoZSBkaWZmZXJlbmNlLiAKCmBgYHtyfQojbG9hZCB0aGUgbG9uZyBkYXRhIAoKbG9uZ19kYXRhIDwtIHJlYWQuY3N2KCJsb25nX3RlbXBlcmF0dXJlLmNzdiIpCgpoZWFkKGxvbmdfZGF0YSkKYGBgCgoKRG8geW91IHNlZSB0aGUgZGlmZmVyZW5jZT8gTm93LCB0aGUgY2F0ZWdvcnkgKHRlbXBfdHlwZSwgb3IgbWVhbiwgbWluLCBhbmQgbWF4KSBpcyBpbiBvbmUgY29sdW1uLCB3aGlsZSBlYWNoIHRlbXBlcmF0dXJlIHRoYXQgY29ycmVzcG9uZHMgdG8gdGhlIHRlbXBfdHlwZSBhbmQgZGF5IGlzIGluIHRoZSB0ZW1wIGNvbHVtbi4gVGhlIHdpZGUgYW5kIGxvbmcgZGF0YSBzZXRzIGFyZSBqdXN0IGRpZmZlcmVudCB3YXlzIG9mIHN0b3JpbmcgdGhlIHNhbWUgZGF0YSEgTm93IGxldCdzIHNlZSBob3cgdGhpcyB3b3JrcyBpbiBnZ3Bsb3QyLiAKCmBgYHtyfQoKI05vdywgaW5zdGVhZCBvZiB0aHJlZSBnZW9tIGxheWVycywgd2Ugd2lsbCBuZWVkIHRvIHBsb3QgdGhlIGRhdGEgYnkgdGhyZWUgZ3JvdXBzOiBtZWFuLCBtaW4sIGFuZCBtYXguIEJlY2F1c2Ugd2UgYXJlIGdyb3VwaW5nIHRoZSBkYXRhIGluIHRoZSBkYXRhZnJhbWUgYnkgdGhlIHR5cGUgb2YgdGVtcGVyYXR1cmUgcmVjb3JkZWQsIHdlIG5lZWQgdG8gYXNzaWduIHRoZSB0ZW1wX3R5cGUgY29sdW1uIHRvIHRoZSBncm91cCBhcmd1bWVudC4gQmVjYXVzZSBlYWNoIHR5cGUgb2YgdGVtcGVyYXR1cmUgd2lsbCBhbHNvIGhhdmUgYSBkaWZmZXJlbnQgY29sb3IsIHdlIHdpbGwgYXNzaWduIHRlbXBfdHlwZSB0byB0aGUgY29sb3IgYXJndW1lbnQgYXMgd2VsbC4gTGV0J3Mgc2VlIHdoYXQgdGhpcyBsb29rcyBsaWtlIQoKZ2dwbG90KGxvbmdfZGF0YSwgYWVzKHggPSBEYXksIHkgPSB0ZW1wLCBjb2xvciA9IHRlbXBfdHlwZSkpICsKICBnZW9tX3BvaW50KCkgKwogIGxhYnMoeSA9ICJUZW1wZXJhdHVyZSIsIHggPSAiRGF5IiwgCiAgICAgICB0aXRsZSA9ICJEYWlseSBUZW1wZXJhdHVyZSBpbiBOZXcgWW9yayBDaXR5LCAyMDE0IiwKICAgICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIChGKSIpCmBgYAoKRG8geW91IHNlZSB3aHkgSSBjaGFuZ2VkIHRoZSBjb2x1bW4gbmFtZXM/IFIgdXNlcyB0aGUgY2F0ZWdvcmllcyBpbiB0aGUgdGVtcF90eXBlIGNvbHVtbiB0byBhZGQgbmFtZXMgdG8gdGhlIGxlZ2VuZC4gS2VlcGluZyB0aGUgImFjdHVhbF9tZWFuX3RlbXAiIChhbmQgc28gb24pIGxhYmVscyB3b3VsZCBub3QgaGF2ZSBiZWVuIG5lYXJseSBhcyBjbGVhciBpbiBhIGxlZ2VuZC4gSW4gb3VyIGdyYXBocywgd2Ugc2hvdWxkIGFpbSB0byBzaG93IGNvbXBsZXggaW5mb3JtYXRpb24gaW4gdGhlIHNpbXBsZXN0IHdheSBwb3NzaWJsZSAtIGhhdmluZyBjbGVhciBsZWdlbmQgYW5kIGF4aXMgdGl0bGVzIGlzIGtleSB0byB0aGF0LiBOb3csIGluIHRoaXMgY2FzZSwgdGhlIGNvbG9ycyBhcmVuJ3QgcXVpdGUgcmlnaHQhIExldCdzIHNldCB0aGVtIG1hbnVhbGx5LiAKCmBgYHtyfQojY3JlYXRlIHRoZSBjb2xvciBwYWxldHRlIGZvciB0aGUgZGF0YQojUmVtZW1iZXIsIG9yZGVyIG1hdHRlcnMhIEJhc2VkIG9uIHRoZSBvcmRlciBvZiB0aGUgbGVnZW5kIGluIHRoZSBsYXN0IGdyYXBoLCBJIHdpbGwgaW5jbHVkZSB0aGUgY29sb3IgZm9yIHRoZSBtYXggdGVtcCwgdGhlbiB0aGUgbWVhbiwgdGhlbiB0aGUgbWluLiAKCmNvbG9ycyA8LSBjKCJyZWQiLCAiZ3JheSIsICJibHVlIikKCmdncGxvdChsb25nX2RhdGEsIGFlcyh4ID0gRGF5LCB5ID0gdGVtcCwgY29sb3IgPSB0ZW1wX3R5cGUpKSArCiAgZ2VvbV9wb2ludCgpICsKICBsYWJzKHkgPSAiVGVtcGVyYXR1cmUiLCB4ID0gIkRheSIsIAogICAgICAgdGl0bGUgPSAiRGFpbHkgVGVtcGVyYXR1cmUgaW4gTmV3IFlvcmsgQ2l0eSwgMjAxNCIsCiAgICAgICBjb2xvciA9ICJUZW1wZXJhdHVyZSAoRikiKSsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sb3JzKQpgYGAKCkRvIHlvdSBzZWUgaG93IG11Y2ggc2ltcGxlciBhbmQgc2hvcnRlciB0aGUgZ2dwbG90MiBjb2RlIGlzIG5vdz8gTG9uZyBmb3JtYXQgZGF0YSBpcyBlYXNpZXIgdG8gd29yayB3aXRoLCBidXQgSSB3YW50ZWQgdG8gc2hvdyB5b3UgYm90aCBkYXRhIHR5cGVzIHNvIHRoYXQgeW91IGFyZSBwcmVwYXJlZCBmb3IgYW55IGRhdGEgZm9ybWF0IHRoYXQgeW91IG1pZ2h0IGVuY291bnRlci4gCgpJZiB5b3Ugd2FudCB0byBzZWUgd2hhdCBvdGhlciBjb2xvcnMgYXJlIGF2YWlsYWJsZSBmb3IgY3JlYXRpbmcgY3VzdG9tIGNvbG9yIHBhbGV0dGVzLCBjaGVjayB0aGlzIGxpbms6IGh0dHA6Ly93d3cuc3RhdC5jb2x1bWJpYS5lZHUvfnR6aGVuZy9maWxlcy9SY29sb3IucGRmLiAKClNvIG5vdyB5b3Uga25vdyB0aGUgYmFzaWNzIG9mIGdyYXBoaW5nIHdpdGggZ2dwbG90MiEgVGhlcmUgYXJlIGp1c3QgYSBmZXcgbW9yZSB0b3BpY3MgdG8gY292ZXIgdGhhdCB5b3Ugd2lsbCBmaW5kIGhlbHBmdWwuIEZpcnN0LCB3aGF0IGlmIEkgZG9uJ3Qgd2FudCB0byB1c2UgYSBzY2F0dGVyIHBsb3Q/IEdncGxvdDIgY29tZXMgd2l0aCBhIHdpZGUgcmFuZ2Ugb2YgZ2VvbSBwb3NzaWJpbGl0aWVzISBJdCdzIHNvIGVhc3kgdG8gcHJvZHVjZSBkaWZmZXJlbnQga2luZHMgb2YgcGxvdHMgb2YgeW91ciBkYXRhLiBMZXQncyBtYWtlIGEgbGluZSBwbG90IHdpdGggdGhlIGRhdGEgd2UgYWxyZWFkeSBoYXZlLiAKCmBgYHtyfQoKZ2dwbG90KGxvbmdfZGF0YSwgYWVzKHggPSBEYXksIHkgPSB0ZW1wLCBjb2xvciA9IHRlbXBfdHlwZSkpICsKICBnZW9tX2xpbmUoKSArCiAgbGFicyh5ID0gIlRlbXBlcmF0dXJlIiwgeCA9ICJEYXkiLCAKICAgICAgIHRpdGxlID0gIkRhaWx5IFRlbXBlcmF0dXJlIGluIE5ldyBZb3JrIENpdHksIDIwMTQiLAogICAgICAgY29sb3IgPSAiVGVtcGVyYXR1cmUgKEYpIikrCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNvbG9ycykKCmBgYApUaGUgbGluZSBwbG90IGRvZXNuJ3QgbG9vayBuaWNlIGFuZCBzbW9vdGggYmVjYXVzZSB3ZSdyZSB3b3JraW5nIHdpdGggZGFpbHkgZGF0YSAtIHRoZXJlIGFyZSBhIGxvdCBvZiBkYXRhIHBvaW50cywgYW5kIHRoZSB0ZW1wZXJhdHVyZXMgbW92ZSBhcm91bmQgYSBsb3QhIEJ1dCBhcyB5b3UgY2FuIHNlZSwgc3dpdGNoaW5nIHRvIGEgbGluZSBwbG90IHdhcyBzbyBlYXN5LiBOZXh0LCB3ZSBjYW4gbG9vayBhdCBhIGJhciBwbG90LiBMaW5lIHBsb3RzLCBzY2F0dGVyIHBsb3RzLCBhbmQgYmFyIHBsb3RzIHdpbGwgYmUgdGhlIG1vc3QgY29tbW9uIHBsb3RzIHlvdSdsbCB1c2UuIAoKYGBge3J9CiNSZW1lbWJlciB0aGF0IGJhciBwbG90cyBkb24ndCByZXF1aXJlIHggYW5kIHkgdmFyaWFibGVzIC0gd2UganVzdCBuZWVkIG9uZSB5IHZhcmlhYmxlIChpbiB0aGlzIGNhc2UsIHRlbXBlcmF0dXJlKSBhbmQgY2F0ZWdvcmllcyBmb3IgdGhlIHgtYXhpcyAoaW4gdGhpcyBjYXNlLCB0ZW1wX3R5cGUpLiBMZXQncyBtYWtlIGEgc2ltcGxlIGJhciBwbG90IGZvciBvbmUgZGF5OgoKZGF5MSA8LSBsb25nX2RhdGEgJT4lIGZpbHRlcihEYXkgPT0gMSkKCmdncGxvdChkYXkxLCBhZXMgKHkgPXRlbXAsIHggPSB0ZW1wX3R5cGUsIGZpbGw9dGVtcF90eXBlKSkgKyAKICBnZW9tX2JhcihzdGF0ID0gIklkZW50aXR5IikrCiAgbGFicyh4ID0gIlRlbXBlcmF0dXJlIFR5cGUiLCB5ID0gIlRlbXBlcmF0dXJlIiwgdGl0bGUgPSAiVGVtcGVyYXR1cmVzIGluIE9uZSBEYXkgaW4gTllDIikgKyBzY2FsZV9maWxsX21hbnVhbCAodmFsdWVzID0gY29sb3JzKQoKI1NvbWUgdGhpbmdzIHRvIG5vdGUgYWJvdXQgdGhpcyBjb2RlOiBiZWNhdXNlIEkgaGF2ZSBpbmNsdWRlZCB0aGUgY2F0ZWdvcmllcyBhcyB4LXZhbHVlcywgSSBuZWVkIHRvIGluY2x1ZGUgdGhlIGFyZ3VtZW50IHN0YXQgPSAiSWRlbnRpdHkiIGluIHRoZSBnZW9tX2JhciBsYXllci4gV2l0aG91dCBnb2luZyBpbnRvIHRvbyBtdWNoIGRldGFpbCwgdGhpcyBhcmd1bWVudCB0ZWxscyBSIHRoYXQgdGhlIGhlaWdodCBvZiB0aGUgY29sdW1ucyBzaG91bGQgYmUgZXF1YWwgdG8gdGhlIHRlbXAgdmFsdWVzLiBOb3RlIGFsc28gdGhhdCBpbnN0ZWFkIG9mIGNvbG9yLCB3ZSB1c2UgdGhlIGZpbGw9IGFyZ3VtZW50IGhlcmUgLSB0aGUgY29sb3IgYXJndW1lbnQgaXMgZm9yIGxpbmVzIGFuZCBwb2ludHMsIHdoaWxlIHNvbGlkIHBvbHlnb25zIG5lZWQgdG8gYmUgYXNzaWduZWQgY29sb3JzIHVzaW5nIHRoZSBmaWxsIGFyZ3VtZW50LiBBcyBhbiBleGVyY2lzZSwgdHJ5IHNlZWluZyB3aGF0IGhhcHBlbnMgd2hlbiB5b3UgdXNlIGNvbG9yID0gaW5zdGVhZCEgV2hlbiB5b3UgdXNlIGZpbGwsIHRoZSBzY2FsZV9jb2xvcl9tYW51YWwgYXJndW1lbnQgYWxzbyBjaGFuZ2VzIHRvIHNjYWxlX2ZpbGxfbWFudWFsIHRvIHNldCB0aGUgY29sb3IgcGFsZXR0ZS4gRmluYWxseSwgUiB3aWxsIGF1dG9tYXRpY2FsbHkgZ2VuZXJhdGUgYSBsZWdlbmQgd2hlbiB5b3UgYXNzaWduIGNvbG9ycyB1c2luZyB0aGUgZ3JvdXAgYWVzdGhldGljIC0gSSBkaWRuJ3QgbmVlZCBhIGxlZ2VuZCBpbiB0aGlzIGdyYXBoLCBzbyBJIHVzZWQgdGhlIHRoZW1lKCkgYXJndW1lbnQgdG8gc2V0IHRoZSBsZWdlbmQgcG9zaXRpb24gdG8gIm5vbmUiLiBUaGlzIGRlbGV0ZXMgdGhlIGxlZ2VuZCBmcm9tIHRoZSBwbG90LCBhbmQgaXMgd29ydGggcmVtZW1iZXJpbmcuIApgYGAKTGV0J3MgdGhpbmsgYWJvdXQgb25lIG1vcmUgd2F5IHlvdSBjYW4gY3VzdG9taXplIHlvdXIgcGxvdHM6IGFkZGluZyBhIHZpc3VhbCB0aGVtZS4gVGhlcmUgYXJlIGEgbnVtYmVyIG9mIHRoZW1lcyB5b3UgY2FuIGFkZCB0byB5b3VyIHBsb3QgLSBJIGxpa2UgdGhlIG1pbmltYWwgdGhlbWUgYmVzdC4gIAoKYGBge3J9CgojSSBwcmVmZXIgdGhlIG1pbmltYWwgdGhlbWUgdGhhdCBjb21lcyBsb2FkZWQgd2l0aCBnZ3Bsb3QyIC0gaXQgbWFrZXMgcGxvdHMgbG9vayB2ZXJ5IHNsZWVrIApnZ3Bsb3QobG9uZ19kYXRhLCBhZXMoeCA9IERheSwgeSA9IHRlbXAsIGdyb3VwID0gdGVtcF90eXBlLCBjb2xvciA9IHRlbXBfdHlwZSkpICsKICBnZW9tX2xpbmUoKSArCiAgbGFicyh5ID0gIlRlbXBlcmF0dXJlIiwgeCA9ICJEYXkiLCAKICAgICAgIHRpdGxlID0gIkRhaWx5IFRlbXBlcmF0dXJlIGluIE5ldyBZb3JrIENpdHksIDIwMTQiLAogICAgICAgY29sb3IgPSAiVGVtcGVyYXR1cmUgKEYpIikrCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNvbG9ycykgKwogIHRoZW1lX21pbmltYWwoKQoKbGlicmFyeShnZ3RoZW1lcykKCmBgYAoKT3RoZXIgdGhlbWUgb3B0aW9ucyBpbmNsdWRlIHRoZW1lX2RhcmsoKSwgdGhlbWVfbGlnaHQoKSwgYW5kIHRoZW1lX2dyYXkoKS4gSWYgeW91IHdhbnQgYWRkaXRpb25hbCB0aGVtZXMsIHRoZSBnZ3RoZW1lcyBwYWNrYWdlcyBoYXMgZ3JlYXQgb3B0aW9ucy4gCgpBbmQgdGhlcmUgeW91IGhhdmUgaXQhIFlvdSBhcmUgbm93IGEgcHJvIGF0IHVzaW5nIGdncGxvdDIuIFlvdSBzaG91bGQgaGF2ZSBhbGwgdGhlIHRvb2xzIHlvdSBuZWVkIHRvIG1ha2UgYmVhdXRpZnVsIGFuZCBlZmZlY3RpdmUgdmlzdWFsaXphdGlvbiBpbiBSLiBJZiB5b3Ugd2FudCBtb3JlIGluZm9ybWF0aW9uIG9uIGRpZmZlcmVudCB0eXBlcyBvZiBncmFwaHMsIG9yIHlvdSBqdXN0IHdhbnQgYSBoZWxwZnVsIHJlZmVyZW5jZSB0byByZWZlciB0byBhcyB5b3UgcHJvZ3Jlc3MgdGhyb3VnaCB0aGUgY291cnNlLCB5b3UgY2FuIGZpbmQgYW4gZXhjZWxsZW50IGdncGxvdDIgY2hlYXQgc2hlZXQgaGVyZTogaHR0cHM6Ly93d3cubWF0aHMudXN5ZC5lZHUuYXUvdS9VRy9TTS9TVEFUMzAyMi9yL2N1cnJlbnQvTWlzYy9kYXRhLXZpc3VhbGl6YXRpb24tMi4xLnBkZi4gCgoKUmVzb3VyY2VzCgpGaXZlVGhpcnR5RWlnaHQgKDIwMTQpLiBVUy4gV2VhdGhlciBIaXN0b3J5LiBbRGF0YSBTZXRdLiBSZXRyaWV2ZWQgZnJvbTogaHR0cHM6Ly9naXRodWIuY29tL2ZpdmV0aGlydHllaWdodC9kYXRhL3RyZWUvbWFzdGVyL3VzLXdlYXRoZXItaGlzdG9yeS4gCgpQcmFiaGFrYXJhbiwgUy4gKDIwMTcpLiBUaGUgQ29tcGxldGUgZ2dwbG90MiBUdXRvcmlhbCAtIFBhcnQxIHwgSW50cm9kdWN0aW9uIFRvIGdncGxvdDIuIFJldHJpZXZlZCBmcm9tOiBodHRwOi8vci1zdGF0aXN0aWNzLmNvL0NvbXBsZXRlLUdncGxvdDItVHV0b3JpYWwtUGFydDEtV2l0aC1SLUNvZGUuaHRtbC4gCg==